﻿#include <iostream>

using namespace std;

class StackOnly {
public:
    StackOnly() = default;
    ~StackOnly() = default;

    void* operator new(size_t) = delete; // 禁止在堆上创建对象
    void* operator new[](size_t) = delete; // 禁止在堆上创建数组对象

    // 禁止在 malloc 的内存上 placement(布置摆放) new
    void* operator new(size_t, void* p) = delete;

    // 显式声明并使用全局的定位new版本
    // void* operator new(size_t size, void* ptr) noexcept {
    //     return ::operator new(size, ptr);
    // }
};

/**
    你在类中声明了任何形式的operator new（哪怕只是删除它）：

    cpp
    运行
    class StackOnly {
    public:
        void* operator new(size_t) = delete;  // 声明了类的operator new（即使是删除）
    };


    编译器的行为会发生变化：

    它会优先在类内部查找匹配的operator new版本，而不再自动使用全局版本。
    对于定位 new（new (s) StackOnly），编译器会在类中查找operator new(size_t, void*)这个重载版本。
 */

/**
    在你的代码中：

    类StackOnly声明了operator new(size_t) = delete（属于类的operator new）。
    当你写new (s) StackOnly时，编译器会在StackOnly类内部查找operator new(size_t, void*)（定位 new 需要的版本）。
    但你的类中没有定义这个版本，编译器也不会去全局范围查找（因为类中已有operator new声明，优先查类内部）。
    最终找不到匹配的函数，导致报错：no matching function for call to 'StackOnly::operator new'。
    一句话总结
    类中只要有operator new的声明（包括删除），就会 “屏蔽” 全局版本的查找。定位 new 需要的operator new(size_t, void*)如果在类中找不到，就会报错。这就是 “重载解析规则导致冲突” 的含义。
 */

class Student
{
public:
    Student() {}
};

int main()
{
    system("chcp 65001");

    StackOnly obj4; // 在栈上创建对象
    // StackOnly* obj5 = new StackOnly(); // 编译错误，禁止在

    StackOnly* s = (StackOnly*)malloc(sizeof(StackOnly));
    // new (s) StackOnly;

    // 仅仅是在堆上分配了一块与 Student 类大小相等的原始内存（字节块），但不会对这块内存做任何初始化。
    Student* s1 = (Student*)malloc(sizeof(Student));

    // 它告诉编译器：别再去堆上申请内存，就在 s 这块现成的内存里，帮我“原地”构造一个 Student("步惊云") 对象。
    new (s) Student();

    return 0;
}
